<!DOCTYPE html>
<html lang="en">
  <head>
    <title>whether_point_in_3d_model</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style type="text/css">
      html,body{margin:0;width: 100%;height: 100%;}
    </style>
  </head>

  <body>
    <script src="./three.min.js"></script>
    <script src="./OrbitControls.js"></script>


    <script>
      "use strict";

      var renderer, scene, camera, stats;

      var particles, uniforms ,buffer_geometry, mesh;
      var sphere_geometry,sphere_mesh,sphere_material;

      var raycaster, intersects;
      var mouse, INTERSECTED;


      { // init


        scene = new THREE.Scene();

        camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
        camera.position.set(30,30,30)

        let orth_size=60;
        let orth={};
        orth.left=window.innerWidth / - orth_size;
        orth.right=window.innerWidth / orth_size;
        orth.top=window.innerHeight / orth_size;
        orth.bottom=window.innerHeight / - orth_size;
        var orth_camera = new THREE.OrthographicCamera( orth.left, orth.right, orth.top, orth.bottom, - 500, 1000 );
        orth_camera.position.z=300;

        var camera_rendering=camera;
        // var camera_rendering=orth_camera;

        { // mesh
          // var geometry = new THREE.TorusBufferGeometry( 6, 3, 16, 16 );
          var geometry = new THREE.TorusKnotBufferGeometry( 4, 1, 100, 16 );
          geometry.rotateX(Math.PI/2)
          var material = new THREE.MeshBasicMaterial( { color: 0xffff00,
            side:THREE.DoubleSide,
          } );
          mesh = new THREE.Mesh( geometry, material );
          // scene.add( mesh );

          var geo_wireframe = new THREE.EdgesGeometry( geometry ); // or WireframeGeometry
          var mat_wireframe = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
          var mesh_wireframe = new THREE.LineSegments( geo_wireframe, mat_wireframe );
          scene.add( mesh_wireframe );
        }


        { // points
          var geo_points = new THREE.BufferGeometry();

          var len=100000
          var positions=[];
          let mesh_size=20
          let colors=[];
          for(let i=0;i<len;i++){
            let x=Math.random()*mesh_size-mesh_size/2
            let y=Math.random()*mesh_size-mesh_size/2
            let z=Math.random()*mesh_size-mesh_size/2

            positions.push(x);
            positions.push(y);
            positions.push(z);

            // colors.push((x+mesh_size/2)/mesh_size);
            // colors.push((y+mesh_size/2)/mesh_size);
            // colors.push((z+mesh_size/2)/mesh_size);
            colors.push(1);
            colors.push(0);
            colors.push(0);
          }
          geo_points.addAttribute('position',new THREE.BufferAttribute(new Float32Array(positions),3));
          geo_points.addAttribute('color',new THREE.BufferAttribute(new Float32Array(colors),3));

          var mtl_points = new THREE.PointsMaterial({
            // color:0xff0000,
            size:.3,
            vertexColors: THREE.VertexColors,
          })

          var  mesh_points = new THREE.Points( geo_points, mtl_points );
          scene.add(mesh_points);
        }

        // helper
          // var helper={};
          // helper.gridHelper = new THREE.GridHelper( 20 , 20 );
          // scene.add( helper.gridHelper );

          // helper.geometry_x = new THREE.BoxGeometry( 10 , 0.1 , 0.1 );
          // helper.material_x = new THREE.MeshBasicMaterial( {color:'red'});
          // helper.mesh_x=new THREE.Mesh(helper.geometry_x,helper.material_x);
          // helper.mesh_x.position.x=5;
          // scene.add(helper.mesh_x);

          // helper.geometry_y = new THREE.BoxGeometry( .1 , 10 , 0.1 );
          // helper.material_y = new THREE.MeshBasicMaterial( {color:'green'});
          // helper.mesh_y=new THREE.Mesh(helper.geometry_y,helper.material_y);
          // helper.mesh_y.position.y=5;
          // scene.add(helper.mesh_y);

          // helper.geometry_z = new THREE.BoxGeometry( .1 , .1 , 10 );
          // helper.material_z = new THREE.MeshBasicMaterial( {color:'blue'});
          // helper.mesh_z=new THREE.Mesh(helper.geometry_z,helper.material_z);
          // helper.mesh_z.position.z=5;
          // scene.add(helper.mesh_z);

        renderer = new THREE.WebGLRenderer();
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );

        var controls = new THREE.OrbitControls( camera_rendering, renderer.domElement );



        { // eliminate

          raycaster = new THREE.Raycaster();
          mouse = new THREE.Vector2();
          geometry.computeBoundingBox()

          for(let i=0;i<len;i++){
            if(!geometry.boundingBox.containsPoint({x:positions[i*3],y:positions[i*3+1],z:positions[i*3+2]})){
              geo_points.attributes.position.array[i*3]=0,geo_points.attributes.position.array[i*3+1]=0,geo_points.attributes.position.array[i*3+2]=0
            }
            else{
              raycaster.set( {x:positions[i*3],y:positions[i*3+1],z:positions[i*3+2]}, {x:0,y:0,z:-1} );
              intersects = raycaster.intersectObject( mesh );
              if(intersects.length%2!==1){
                geo_points.attributes.position.array[i*3]=0,geo_points.attributes.position.array[i*3+1]=0,geo_points.attributes.position.array[i*3+2]=0
              }
            }
          }
          geo_points.attributes.position.needsUpdate=true;
        }


        window.addEventListener( 'resize', onWindowResize, false );

      }

      animate();

      function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );

      }

      function animate() {

        requestAnimationFrame( animate );

        render();
        // stats.update();

      }

      function render() {

        renderer.render( scene, camera_rendering );

      }

    </script>

  </body>

</html>
